package com.jml.juc.volatiledemo;

/**
 * 单例模式的安全问题
 * 为什么加了synchonized还要加volatile
 *  instance = new SingletonDemo();分为好几步，
 * 1.分配空间，2.初始化对象，3.把地址指向instance，如果没有加volatile这个顺序是不固定的，
 *     如果第一个线程重排序后执行的顺序是
 * 1.分配空间，3.把地址指向instance，2.初始化值
 *     当第二个线程在第一个线程执行完3.把地址指向instance后正好进入第一个判断
 * 此时判断是非null的第二个线程直接就获取了instance，但是这个instance还没有初始化的
 *就会导致第二个线程拿到的对象是不完整的可能会报错
 */
public class SingletonDemo {
    private volatile static SingletonDemo instance = null;
    private SingletonDemo(){
        System.out.println(Thread.currentThread().getName()+"\t SingletonDemo构造方法执行了");
    }
    public static SingletonDemo getInstance(){
        if (instance == null) {
            synchronized (SingletonDemo.class){
                if (instance == null) {
                    instance = new SingletonDemo();
                }
            }
        }
        return instance;
    }
    public static void main(String[] args) {
        //多线程操作
        for (int i = 1; i <= 100; i++) {
            new Thread(()->{
                SingletonDemo.getInstance();
            }, String.valueOf(i)).start();
        }
    }

}
